#include <stdint.h>
#include <stddef.h>
#include <printf.h>
#include <sched_clock.h>
#if SE_DEBUG
#include <atomic.h>
#include <atomic_se.h>
#include <atomicBitset.h>
#include <atomicBitset_se.h>
#include <trylock.h>
#endif
#include "2440addr.h"
#include "serial.h"
#include "mmu.h"
#include <gpio.h>
#include "Nand.h"
#include "norflash.h"
#include "interrupts.h"
#include "pwm_timer.h"

#if SE_DEBUG
ATOMIC_BITSET_DECL(test_atomic_bitset, 64, static);
static TRYLOCK_DECL_STATIC(test_trylock) = TRYLOCK_INIT_STATIC();
#endif
int main(void)
{
#if SE_DEBUG
    uint64_t now_time = 0, last_time = 0;
    atomic_t test_atomic = ATOMIC_INIT(0);
    uint8_t test_byte = 0, old_byte = 0;
    uint32_t test_word = 0, old_word = 0;
    uint32_t bit = 0;
    bool trylock_result = 0;
    uint8_t *heap_test = NULL;
#endif
    mmu_init();
    gpio_init();
    Uart_Init();
    Uart_SendByte('\n');
    vprintk("<***********************************************>\n");
    vprintk("           S3C2440 Test Program in GCC\n");
    vprintk("<***********************************************>\n");
    sched_clock_timer_init();
    sched_clock_init();
    enable_irq();

    extern void osMain(void);
    osMain();

    while (1);

#if SE_DEBUG
    atomicBitsetInit(test_atomic_bitset, 64);
    vprintk("system time:%lld\n", sched_clock());
    last_time = sched_clock();

    while (1) {
        now_time = sched_clock();

        if ((now_time - last_time) > 2000000000) {
            last_time = now_time;
            vprintk("now_time:%lld\n", now_time);
            atomic_add(1, &test_atomic);
            vprintk("test_atomic:%d\n", atomic_read(&test_atomic));

            atomicAddByte(&test_byte, 1);
            vprintk("atomicAddByte:%d\n", atomicReadByte(&test_byte));
            old_byte = atomicXchgByte(&test_byte, 3);
            vprintk("atomicXchgByte, old:%d, new:%d\n", old_byte, atomicReadByte(&test_byte));

            atomicAdd32bits(&test_word, 2);
            vprintk("atomicAdd32bits:%d\n", atomicRead32bits(&test_word));
            old_word = atomicXchg32bits(&test_word, 4);
            vprintk("atomicXchgByte, old:%d, new:%d\n", old_word, atomicRead32bits(&test_word));

            bit = atomicBitsetFindClearAndSet(test_atomic_bitset);
            vprintk("atomicBitsetFindClearAndSet, bit:%d\n", bit);
            trylock_result = trylockTryTake(&test_trylock);
            vprintk("trylockTryTake, trylock_result:%d, addr:%p\n", trylock_result, &test_trylock.lock);
            heap_test = heapAlloc(32);
            vprintk("heapAlloc, heap_test:%d\n", heap_test);
            trylockRelease(&test_trylock);
        }
    }

#endif
}

